package com.edoomath.api.servcice.impl;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.demo2do.core.persistence.GenericDaoSupport;
import com.demo2do.core.persistence.annotation.Dao;
import com.demo2do.core.utils.CollectionUtils;
import com.demo2do.core.utils.JsonUtils;
import com.edoomath.api.dao.CourseDao;
import com.edoomath.api.dao.CourseItemDao;
import com.edoomath.api.dao.UserCourseDao;
import com.edoomath.api.servcice.UserCourseService;
import com.edoomath.entity.course.Course;
import com.edoomath.entity.course.CourseAttribute;
import com.edoomath.entity.course.CourseItem;
import com.edoomath.entity.course.CourseItemStat;
import com.edoomath.entity.course.CourseMaterail;
import com.edoomath.entity.course.MaterialType;
import com.edoomath.entity.user.User;
import com.edoomath.entity.usercourse.UserCourse;
import com.edoomath.entity.usercourse.UserCourseAttribute;
import com.edoomath.entity.usercourse.UserCourseItem;
import com.edoomath.entity.usercourse.UserCourseStat;
import com.edoomath.entity.usercourse.UserCourseTask;

/**
 * 
 * @author mohanlan
 *
 */
@Service("userCourseService")
public class UserCourseServiceImpl extends DataServiceImpl<UserCourse> implements UserCourseService {
	
	private static final Logger logger = LoggerFactory.getLogger(UserCourseServiceImpl.class);
	
	@Dao
	private UserCourseDao userCourseDao;
	
	@Dao
	private CourseDao courseDao;
	
	@Dao
	private CourseItemDao courseItemDao;
	
	@Autowired
	private GenericDaoSupport genericDaoSupport;
	
	/*
	 * (non-Javadoc)
	 * @see com.edoomath.api.servcice.UserCourseService#loadUserCourse(java.lang.String, java.lang.Long)
	 */
	public UserCourse loadUserCourse(String unionid, Long courseId) {
		return userCourseDao.loadUserCourse(unionid, courseId);
	}
	
	/*
	 * (non-Javadoc)
	 * @see com.edoomath.api.servcice.UserCourseService#loadStat(com.edoomath.entity.usercourse.UserCourse)
	 */
	public UserCourseStat loadStat(UserCourse userCourse) {
		return userCourseDao.loadUserCourseStat(userCourse);
	}

	/*
	 * (non-Javadoc)
	 * @see com.edoomath.api.servcice.UserCourseService#loadUserCourse(java.lang.String)
	 */
	public List<UserCourse> listUserCourse(String unionid) {
		return userCourseDao.listUserCourse(unionid);
	}
	
	/*
	 * (non-Javadoc)
	 * @see com.edoomath.api.servcice.UserCourseService#create(com.edoomath.entity.user.User, com.edoomath.entity.course.Course)
	 */
	public UserCourse create(User user, Course course, String opengid) {
		
		UserCourse userCourse = userCourseDao.loadUserCourse(user.getUnionid(), course.getId());
		
		// create user course & user course item
		if(userCourse == null) {
			
			// 1. create user course
			userCourse = new UserCourse(user, course, opengid);
			genericDaoSupport.save(userCourse);
			
			// 2. create user course attribute
			List<CourseAttribute> courseAttrs = courseDao.listAttrs(course);
			
			logger.trace("get attrs [{}]", JsonUtils.toJson(courseAttrs));
			
			for(CourseAttribute attr : courseAttrs) {
				UserCourseAttribute userCourseAttribute = new UserCourseAttribute(userCourse, attr.getName(), attr.getValue());
				genericDaoSupport.save(userCourseAttribute);
			}
			
			Map<String, CourseAttribute> attrsMap = CollectionUtils.constructMapValue(courseAttrs, "name");
			UserCourseStat userCourseStat = new UserCourseStat(userCourse, Integer.parseInt(attrsMap.get("item_count").getValue()), Integer.parseInt(attrsMap.get("task_count").getValue()));
			genericDaoSupport.save(userCourseStat);
			
			// 3. generate user course item
			this.genegrateUserCourseItem(userCourse, attrsMap.get("unlock_count"));
			
			// 4. create user course task
			this.generateUserCourseTask(userCourse, attrsMap.get("unlock_count"));
			
		}
		
		return userCourse;
	}
	
	/*
	 * (non-Javadoc)
	 * @see com.edoomath.api.servcice.UserCourseService#listUserCourseItem(com.edoomath.entity.user.User, com.edoomath.entity.course.Course)
	 */
	public List<UserCourseItem> listUserCourseItem(UserCourse userCourse) {
		return userCourseDao.listUserCourseItem(userCourse);
	}
	
	/*
	 * (non-Javadoc)
	 * @see com.edoomath.api.servcice.UserCourseService#listUserCourseAttrs(List)
	 */
	public Map<String, Map<String, UserCourseAttribute>> listUserCourseAttrs( List<UserCourse> userCourses) {
		if(org.apache.commons.collections.CollectionUtils.isNotEmpty(userCourses)) {
			List<UserCourseAttribute> attrs = userCourseDao.listAttrs(userCourses);
			
			Map<String , List<UserCourseAttribute>> courseAttrs = CollectionUtils.constructMapValues(attrs, "userCourse.course.id");
			
			Map<String, Map<String, UserCourseAttribute>> result = new HashMap<String, Map<String, UserCourseAttribute>>();
			
			for(String key : courseAttrs.keySet()) {
				Map<String, UserCourseAttribute> item = CollectionUtils.constructMapValue(courseAttrs.get(key), "name");
				result.put(key, item);
			}
			
			return result;
		} else {
			return null;
		}
	}
	
	/*
	 * (non-Javadoc)
	 * @see com.edoomath.api.servcice.UserCourseService#listUserCourseAttribute(com.edoomath.entity.usercourse.UserCourse)
	 */
	public List<UserCourseAttribute> listUserCourseAttribute(UserCourse userCourse) {
		return userCourseDao.listAttrs(userCourse);
	}
	
	/*
	 * (non-Javadoc)
	 * @see com.edoomath.api.servcice.UserCourseService#listUserCourseStat(com.edoomath.entity.user.User)
	 */
	public List<UserCourseStat> listUserCourseStat(String unionid) {
		return userCourseDao.listUserCourseStat(unionid);
	}
	
	/*
	 * (non-Javadoc)
	 * @see com.edoomath.api.servcice.UserCourseService#listUserCourseTasks(com.edoomath.entity.usercourse.UserCourse)
	 */
	public Map<String, List<UserCourseTask>> listUserCourseTasks(UserCourse userCourse) {
		
		List<UserCourseTask> tasks = userCourseDao.listUserCourseTasks(userCourse);
		Map<String, List<UserCourseTask>> result = CollectionUtils.constructMapValues(tasks, "courseItem.name");
		return result;
	}
	
	/**
	 * 
	 * @param userCourse
	 * @return
	 */
	private void genegrateUserCourseItem(UserCourse userCourse, CourseAttribute courseAttribute) {
		
		logger.trace("attrs [{}]", JsonUtils.toJson(courseAttribute));
		
		Course course = userCourse.getCourse();

		List<CourseItem> courseItems = courseItemDao.list(course);
		List<CourseItemStat> courseItemStats = courseItemDao.listCourseItemStat(courseItems);
		Map<String, CourseItemStat> courseItemStatsMap = CollectionUtils.constructMapValue(courseItemStats, "courseItem.id");
		
		int lockIndex = courseAttribute == null ? 1 :  Integer.parseInt(courseAttribute.getValue());
		logger.trace("lockIndex [{}]", lockIndex);
		
		for(int i=0; i < courseItems.size(); i++ ) {
			CourseItemStat stat = courseItemStatsMap.get(courseItems.get(i).getId().toString());
			UserCourseItem userCourseItem = new UserCourseItem(userCourse, userCourse.getUser(), courseItems.get(i), stat);
			if(i < lockIndex) {
				genericDaoSupport.save(userCourseItem.initliazeProcessing(i+1));
			} else {
				genericDaoSupport.save(userCourseItem.initliaze(i+1));
			}
			
			genericDaoSupport.update(stat.addJoinNumber());
			
		}
		
	}
	
	/**
	 * 
	 * @param userCourse
	 * @param firstItemId
	 */
	private void generateUserCourseTask(UserCourse userCourse, CourseAttribute courseAttribute) {
		
		logger.trace("attrs [{}]", JsonUtils.toJson(courseAttribute));
		
		Course course = userCourse.getCourse();
		
		if(course.isNeedSignin()) {
			
			List<CourseItem> courseItems = courseItemDao.list(course);
			int lockIndex = courseAttribute == null ? 1 :  Integer.parseInt(courseAttribute.getValue());
			logger.trace("lockIndex [{}]", lockIndex);
			
			for(int i=0; i < courseItems.size(); i++ ) {
				
				if(i < lockIndex) {
					List<CourseMaterail> materails = courseDao.listItemMaterials(courseItems.get(i), MaterialType.EXERCISES.name());
					for(CourseMaterail materail : materails) {
						UserCourseTask userCourseTask = new UserCourseTask(userCourse, materail);
						genericDaoSupport.save(userCourseTask.initliazeProcessing(materail.getCourseItem().getSorting()));
					}
				}
			}
		}
	}

}
